﻿using System;
using System.Collections.Generic;
using System.Globalization;
using SymbolIntegration.core.Helpers;

namespace SymbolIntegration.core.Expressions
{
    public class ConstantExpression : Expression
    {
        private readonly double m_Value;

        static internal ConstantExpression ParseItself(string expression, int position, int size)
        {
            ParseUtils.TrimScopes(expression, ref position, ref size);
            var subExpr = expression.Substring(position, size);
            double dValue;
            bool isSuccess = Double.TryParse(subExpr, out dValue);
            if (!isSuccess)
            {
                throw new ParseException("Expression is not number", expression, position, size, 0);
            }
            var expr = new ConstantExpression(dValue);
            return expr;
        }
        
        public ConstantExpression(double value)
        {
            m_Value = value;
        }

        public double Value
        {
            get { return m_Value; }
        }

        public override Expression Clone()
        {
            var expr = new ConstantExpression(m_Value);
            InnerCopy(expr);
            return expr;
        }

        public override ExpressionType Type
        {
            get { return ExpressionType.Constant; }
        }

        public override Expression Substitute(Dictionary<string, Expression> varValues)
        {
            return this;
        }

        public override Expression Differentiate(string variable)
        {
            return new ConstantExpression(0);
        }

        public override Expression Normalize()
        {
            var value = IsNegate ? -m_Value : m_Value;
            var result = new ConstantExpression(value);
            return result;
        }

        public override bool IsEqual(Expression right)
        {
            bool result = false;
            do
            {
                if (right.IsNegate != IsNegate)
                {
                    break;
                }

                var x = right as ConstantExpression;
                if (x == null)
                {
                    break;
                }

                if (!MathHelper.AlmostEqual(x.Value, Value))
                {
                    break;
                }

                result = true;
            }
            while (false);

            return result;
        }

        public override Polinom FormatToPolinomAsDependentFromVariable(string variable)
        {
            var polinom = new Polinom(variable);
            polinom.SetConstantAt(0, Normalize());
            return polinom;
        }

        public override string ToString()
        {
            double value = m_Value;
            if (IsNegate)
            {
                value *= -value;
            }
            var newValue = Math.Round(value, 4);
            var result = newValue.ToString(CultureInfo.CurrentUICulture);
            if (value < 0)
            {
                result = "(" + result + ")";
            }
            return result;
        }

        protected internal override void RebuildDependancyCache()
        {
            m_Cache.Varibles.Clear();
            m_Cache.IsValid = true;
        }

        protected internal override void FillExpressionStatistic(ExpressionStatistic statistic, string integrateVariable)
        {
            //Nothing to fill
        }

        protected internal override Expression IntegrateAsDependentFromVar(string variable, IIntegrator integrator)
        {
            return new VariableExpression(variable) * this;
        }
    }
}
